"""Device Bridge integration for Home Assistant."""

import logging
from typing import Dict, Any
import json
import qrcode
import io
import base64
from datetime import datetime, timedelta
import secrets
import os

from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers import device_registry as dr
from homeassistant.components.http import HomeAssistantView
from homeassistant.const import STATE_ON, STATE_OFF
from aiohttp import web
import aiohttp_cors

from .const import DOMAIN, API_ENDPOINT, QR_CODE_SERVICE
from .frontend import async_setup_frontend

_LOGGER = logging.getLogger(__name__)

PLATFORMS = []


async def async_setup(hass: HomeAssistant, config: Dict[str, Any]) -> bool:
    """Set up the Device Bridge component."""
    hass.data.setdefault(DOMAIN, {})
    return True


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Set up Device Bridge from a config entry."""
    _LOGGER.info("Setting up Device Bridge")

    # 初始化数据存储
    hass.data.setdefault(DOMAIN, {})

    # 创建设备桥接管理器
    bridge_manager = DeviceBridgeManager(hass, entry)
    hass.data[DOMAIN][entry.entry_id] = bridge_manager

    # 注册HTTP API视图
    await bridge_manager.setup_api_views()

    # 注册服务
    await bridge_manager.setup_services()

    # 设置前端面板
    await async_setup_frontend(hass)

    # 自动生成二维码
    if entry.data.get("auto_generate_qr", True):
        _LOGGER.info("自动生成二维码...")
        await bridge_manager.generate_qr_code({"client_name": "default"})

    _LOGGER.info("Device Bridge setup completed")
    return True


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Unload a config entry."""
    _LOGGER.info("Unloading Device Bridge")

    # 清理数据
    if entry.entry_id in hass.data[DOMAIN]:
        bridge_manager = hass.data[DOMAIN].pop(entry.entry_id)
        await bridge_manager.cleanup()

    return True


class DeviceBridgeManager:
    """管理设备桥接功能"""

    def __init__(self, hass: HomeAssistant, entry: ConfigEntry):
        self.hass = hass
        self.entry = entry
        self.api_tokens = {}  # 存储API访问令牌
        self.device_cache = {}  # 缓存设备信息
        self.current_qr_data = None  # 存储当前二维码数据
        self.token_file = os.path.join(
            hass.config.config_dir, ".storage", "device_bridge_tokens.json"
        )
        # 添加订阅持久化文件路径
        self.subscriptions_file = os.path.join(
            hass.config.config_dir, ".storage", "device_bridge_subscriptions.json"
        )
        self.persistent_subscriptions = {}  # 持久化订阅存储

        # 启动时加载已保存的token和订阅
        self._load_tokens()
        self._load_subscriptions()

    def _load_subscriptions(self):
        """从文件加载持久化订阅"""
        try:
            if os.path.exists(self.subscriptions_file):
                with open(self.subscriptions_file, "r", encoding="utf-8") as f:
                    data = json.load(f)
                    self.persistent_subscriptions = data
                    _LOGGER.info(
                        f"已加载 {len(self.persistent_subscriptions)} 个持久化订阅"
                    )
        except Exception as e:
            _LOGGER.error(f"加载订阅文件失败: {e}")
            self.persistent_subscriptions = {}

    def _save_subscriptions(self):
        """保存订阅到文件"""
        try:
            os.makedirs(os.path.dirname(self.subscriptions_file), exist_ok=True)
            with open(self.subscriptions_file, "w", encoding="utf-8") as f:
                json.dump(
                    self.persistent_subscriptions, f, ensure_ascii=False, indent=2
                )
            _LOGGER.debug("持久化订阅已保存")
        except Exception as e:
            _LOGGER.error(f"保存订阅文件失败: {e}")

    def add_persistent_subscription(self, client_id: str, entity_ids: list):
        """添加持久化订阅"""
        if client_id not in self.persistent_subscriptions:
            self.persistent_subscriptions[client_id] = []

        # 去重添加
        existing_entities = set(self.persistent_subscriptions[client_id])
        new_entities = set(entity_ids)
        self.persistent_subscriptions[client_id] = list(
            existing_entities.union(new_entities)
        )

        self._save_subscriptions()
        _LOGGER.info(f"客户端 {client_id} 添加了持久化订阅: {entity_ids}")

    def remove_persistent_subscription(self, client_id: str, entity_ids: list = None):
        """移除持久化订阅"""
        if client_id not in self.persistent_subscriptions:
            return

        if entity_ids is None:
            # 移除所有订阅
            del self.persistent_subscriptions[client_id]
        else:
            # 移除指定订阅
            existing_entities = set(self.persistent_subscriptions[client_id])
            removed_entities = set(entity_ids)
            self.persistent_subscriptions[client_id] = list(
                existing_entities - removed_entities
            )

            # 如果订阅列表为空，删除客户端记录
            if not self.persistent_subscriptions[client_id]:
                del self.persistent_subscriptions[client_id]

        self._save_subscriptions()
        _LOGGER.info(f"客户端 {client_id} 移除了持久化订阅: {entity_ids}")

    def get_persistent_subscriptions(self, client_id: str) -> list:
        """获取客户端的持久化订阅"""
        return self.persistent_subscriptions.get(client_id, [])

    def _load_tokens(self):
        """从文件加载已保存的token"""
        try:
            if os.path.exists(self.token_file):
                with open(self.token_file, "r", encoding="utf-8") as f:
                    data = json.load(f)
                    # 转换日期字符串回datetime对象
                    for token, info in data.items():
                        if "created_at" in info:
                            info["created_at"] = datetime.fromisoformat(
                                info["created_at"]
                            )
                    self.api_tokens = data
                    _LOGGER.info(f"已加载 {len(self.api_tokens)} 个保存的token")
        except Exception as e:
            _LOGGER.error(f"加载token文件失败: {e}")
            self.api_tokens = {}

    def _save_tokens(self):
        """保存token到文件"""
        try:
            # 确保存储目录存在
            os.makedirs(os.path.dirname(self.token_file), exist_ok=True)

            # 转换datetime对象为字符串以便JSON序列化
            data_to_save = {}
            for token, info in self.api_tokens.items():
                info_copy = info.copy()
                if "created_at" in info_copy:
                    info_copy["created_at"] = info_copy["created_at"].isoformat()
                data_to_save[token] = info_copy

            with open(self.token_file, "w", encoding="utf-8") as f:
                json.dump(data_to_save, f, ensure_ascii=False, indent=2)
            _LOGGER.debug("Token已保存到文件")
        except Exception as e:
            _LOGGER.error(f"保存token文件失败: {e}")

    async def setup_api_views(self):
        """设置API视图"""
        # 注册API视图
        self.hass.http.register_view(DeviceListView(self))
        self.hass.http.register_view(DeviceControlView(self))
        self.hass.http.register_view(DeviceStatusView(self))
        self.hass.http.register_view(QRCodeView(self))

        # 注册WebSocket视图
        self.websocket_view = DeviceWebSocketView(self)
        self.hass.http.register_view(self.websocket_view)

        _LOGGER.info("Device Bridge API视图已注册")

        # 使用视图类中的cors_allowed = True，Home Assistant会自动处理CORS
        # 不需要手动设置CORS，避免frozen list错误

    async def setup_services(self):
        """设置服务"""

        async def generate_qr_code_service(call: ServiceCall):
            """生成二维码服务"""
            await self.generate_qr_code(call.data)

        self.hass.services.async_register(
            DOMAIN, QR_CODE_SERVICE, generate_qr_code_service
        )

        _LOGGER.info("Device Bridge服务已注册")

    async def cleanup(self):
        """清理资源"""
        # 清理WebSocket资源
        if hasattr(self, "websocket_view"):
            await self.websocket_view.cleanup()

        # 保存token到文件（清理时不删除token，保持永久有效）
        self._save_tokens()
        self.device_cache.clear()
        self.current_qr_data = None

    def generate_api_token(self, client_name: str = "default") -> str:
        """生成API访问令牌 - 永久有效"""
        # 检查是否已存在永久token
        for token, info in self.api_tokens.items():
            if info["client_name"] == client_name and info.get("permanent", False):
                _LOGGER.info(f"使用现有永久token: {client_name}")
                return token

        # 生成新的永久token
        token = secrets.token_urlsafe(32)
        self.api_tokens[token] = {
            "client_name": client_name,
            "created_at": datetime.now(),
            "permanent": True,  # 标记为永久token
        }

        # 保存到文件
        self._save_tokens()

        _LOGGER.info(f"生成新的永久token: {client_name}")
        return token

    def validate_token(self, token: str) -> bool:
        """验证API令牌 - 支持永久token"""
        _LOGGER.debug(f"验证token: {token[:10]}...")
        _LOGGER.debug(f"当前存储的tokens: {list(self.api_tokens.keys())}")

        if not token:
            _LOGGER.warning("Token为空")
            return False

        if token not in self.api_tokens:
            _LOGGER.warning(f"Token不存在: {token[:10]}...")
            return False

        token_info = self.api_tokens[token]

        # 检查是否为永久token
        if token_info.get("permanent", False):
            _LOGGER.info(f"永久Token验证成功: {token_info['client_name']}")
            return True

        # 检查临时token是否过期
        current_time = datetime.now()
        if "expires_at" in token_info and current_time > token_info["expires_at"]:
            _LOGGER.warning(
                f"Token已过期: {token[:10]}..., 过期时间: {token_info['expires_at']}"
            )
            del self.api_tokens[token]
            return False

        _LOGGER.info(f"Token验证成功: {token_info['client_name']}")
        return True

    def _should_filter_device(
        self, entity_id: str, state, device_class: str = None
    ) -> bool:
        """判断是否应该过滤掉该设备"""
        # 只保留主要的可控制设备域名
        domain = entity_id.split(".")[0]
        allowed_domains = ["switch", "light", "cover", "fan", "climate", "lock"]

        # 如果不是允许的域名，则过滤掉
        if domain not in allowed_domains:
            return True

        # 过滤功率和电量传感器
        if domain == "sensor":
            # 根据设备类别过滤
            if device_class in ["power", "energy"]:
                return True

            # 根据单位过滤
            unit = state.attributes.get("unit_of_measurement", "")
            if unit.lower() in ["w", "kw", "mw", "wh", "kwh", "mwh"]:
                return True

            # 根据名称关键词过滤
            name = state.attributes.get("friendly_name", entity_id).lower()
            power_keywords = ["功率", "power", "电量", "energy", "耗电", "用电"]
            if any(keyword in name for keyword in power_keywords):
                return True

        # 过滤聚合设备
        name = state.attributes.get("friendly_name", entity_id).lower()
        entity_id_lower = entity_id.lower()

        # 过滤包含聚合关键词的设备
        aggregate_keywords = [
            "聚合",
            "aggregate",
            "switch switch",
            "总开关",
            "主开关",
            "总控",
            "集合",
        ]

        # 检查friendly_name和entity_id
        for keyword in aggregate_keywords:
            if keyword in name or keyword in entity_id_lower:
                return True

        # 过滤特定模式的entity_id (如: switch.xxx_switch) - 但要更精确
        if domain == "switch":
            entity_name = entity_id.split(".")[-1]
            # 只过滤明显的聚合开关，避免误杀正常设备
            if entity_name.endswith("_switch_switch") or entity_name == "switch":
                return True

        # 过滤米家设备的指示灯和设备信息
        xiaomi_filter_keywords = [
            "指示灯",
            "indicator",
            "led",
            "light_indicator",
            "设备信息",
            "device_info",
            "info",
            "状态",
            "status",
            "信号强度",
            "signal",
            "rssi",
            "wifi",
            "网络",
            "温度",
            "temperature",
            "湿度",
            "humidity",
            "电池",
            "battery",
            "版本",
            "version",
            "固件",
            "firmware",
            "mac",
            "ip",
            "连接",
            "connection",
            "在线",
            "online",
            "更新",
            "update",
            "升级",
            "upgrade",
            "重启",
            "restart",
            "模式",
            "mode",
            "场景",
            "scene",
            "定时",
            "timer",
            "倒计时",
            "countdown",
            "延时",
            "delay",
        ]

        # 检查是否为米家设备的辅助实体
        for keyword in xiaomi_filter_keywords:
            if keyword in name or keyword in entity_id_lower:
                return True

        # 如果通过了所有过滤条件，则保留该设备
        return False

    async def get_aggregated_devices(self) -> Dict[str, Any]:
        """获取聚合的设备信息"""
        devices = {}
        entity_registry = er.async_get(self.hass)
        device_registry = dr.async_get(self.hass)

        # 从mindor-cloud获取设备
        mindor_devices = await self._get_mindor_devices()
        devices.update(mindor_devices)

        # 从xiaomi_device_hub获取设备
        xiaomi_devices = await self._get_xiaomi_devices()
        devices.update(xiaomi_devices)

        # 转换为数组格式，添加统计信息
        device_list = list(devices.values())

        # 按设备类型分组统计
        stats = {
            "total": len(device_list),
            "mindor_cloud": len(
                [d for d in device_list if d["type"] == "mindor_cloud"]
            ),
            "xiaomi": len([d for d in device_list if d["type"] == "xiaomi"]),
            "by_domain": {},
        }

        # 按域名统计
        for device in device_list:
            domain = device["domain"]
            if domain not in stats["by_domain"]:
                stats["by_domain"][domain] = 0
            stats["by_domain"][domain] += 1

        return {
            "success": True,
            "data": device_list,
            "stats": stats,
            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        }

    async def _get_mindor_devices(self) -> Dict[str, Any]:
        """获取mindor-cloud设备"""
        devices = {}

        # 查找mindor-cloud实体
        entity_registry = er.async_get(self.hass)
        for entity_id, entity in entity_registry.entities.items():
            if entity.platform == "mindor_cloud":
                state = self.hass.states.get(entity_id)
                if state:
                    device_class = state.attributes.get("device_class")

                    # 过滤功率和电量传感器
                    if self._should_filter_device(entity_id, state, device_class):
                        continue

                    devices[entity_id] = {
                        "id": entity_id,
                        "name": state.attributes.get("friendly_name", entity_id),
                        "type": "mindor_cloud",
                        "domain": entity_id.split(".")[0],
                        "state": state.state,
                        "attributes": dict(state.attributes),
                        "device_class": device_class,
                        "unit_of_measurement": state.attributes.get(
                            "unit_of_measurement"
                        ),
                    }

        return devices

    async def _get_xiaomi_devices(self) -> Dict[str, Any]:
        """获取xiaomi设备"""
        devices = {}

        # 查找xiaomi_miot实体
        entity_registry = er.async_get(self.hass)
        for entity_id, entity in entity_registry.entities.items():
            if entity.platform == "xiaomi_miot":
                state = self.hass.states.get(entity_id)
                if state:
                    device_class = state.attributes.get("device_class")

                    # 过滤功率和电量传感器
                    if self._should_filter_device(entity_id, state, device_class):
                        continue

                    devices[entity_id] = {
                        "id": entity_id,
                        "name": state.attributes.get("friendly_name", entity_id),
                        "type": "xiaomi",
                        "domain": entity_id.split(".")[0],
                        "state": state.state,
                        "attributes": dict(state.attributes),
                        "device_class": device_class,
                        "unit_of_measurement": state.attributes.get(
                            "unit_of_measurement"
                        ),
                    }

        return devices

    async def control_device(self, entity_id: str, action: str, **kwargs) -> bool:
        """控制设备"""
        try:
            domain = entity_id.split(".")[0]

            # 添加调试日志
            _LOGGER.info(f"控制设备: {entity_id}, 动作: {action}, 参数: {kwargs}")

            if action == "turn_on":
                await self.hass.services.async_call(
                    domain, "turn_on", {"entity_id": entity_id}
                )
            elif action == "turn_off":
                await self.hass.services.async_call(
                    domain, "turn_off", {"entity_id": entity_id}
                )
            elif action == "toggle":
                await self.hass.services.async_call(
                    domain, "toggle", {"entity_id": entity_id}
                )
            elif action == "set_position" and domain == "cover":
                position = kwargs.get("position", 50)
                await self.hass.services.async_call(
                    domain,
                    "set_cover_position",
                    {"entity_id": entity_id, "position": position},
                )
            elif action == "open_cover" and domain == "cover":
                await self.hass.services.async_call(
                    domain, "open_cover", {"entity_id": entity_id}
                )
            elif action == "close_cover" and domain == "cover":
                await self.hass.services.async_call(
                    domain, "close_cover", {"entity_id": entity_id}
                )
            elif action == "stop_cover" and domain == "cover":
                await self.hass.services.async_call(
                    domain, "stop_cover", {"entity_id": entity_id}
                )
            elif action == "set_temperature" and domain == "climate":
                temperature = kwargs.get("temperature", 22)
                await self.hass.services.async_call(
                    domain,
                    "set_temperature",
                    {"entity_id": entity_id, "temperature": temperature},
                )
            elif action == "set_hvac_mode" and domain == "climate":
                hvac_mode = kwargs.get("hvac_mode")
                if not hvac_mode:
                    _LOGGER.error(f"缺少 hvac_mode 参数")
                    return False
                _LOGGER.info(f"设置空调模式: {hvac_mode}")
                await self.hass.services.async_call(
                    domain,
                    "set_hvac_mode",
                    {"entity_id": entity_id, "hvac_mode": hvac_mode},
                )
            elif action == "set_fan_mode" and domain == "climate":
                fan_mode = kwargs.get("fan_mode")
                if not fan_mode:
                    _LOGGER.error(f"缺少 fan_mode 参数")
                    return False
                _LOGGER.info(f"设置风速模式: {fan_mode}")
                await self.hass.services.async_call(
                    domain,
                    "set_fan_mode",
                    {"entity_id": entity_id, "fan_mode": fan_mode},
                )
            elif action == "set_swing_mode" and domain == "climate":
                swing_mode = kwargs.get("swing_mode")
                if not swing_mode:
                    _LOGGER.error(f"缺少 swing_mode 参数")
                    return False
                _LOGGER.info(f"设置扫风模式: {swing_mode}")

                # 检查设备当前状态和支持的扫风模式
                state = self.hass.states.get(entity_id)
                if state:
                    supported_swing_modes = state.attributes.get("swing_modes", [])
                    _LOGGER.info(f"设备支持的扫风模式: {supported_swing_modes}")

                    if swing_mode not in supported_swing_modes:
                        _LOGGER.warning(
                            f"设备不支持扫风模式 '{swing_mode}'，支持的模式: {supported_swing_modes}"
                        )

                        # 改进的扫风模式映射，支持中文
                        swing_mode_mapping = {
                            # 水平/左右扫风
                            "horizontal": [
                                "horizontal",
                                "left_right",
                                "lr",
                                "左右",
                                "左右扫风",
                            ],
                            "left_right": [
                                "horizontal",
                                "left_right",
                                "lr",
                                "左右",
                                "左右扫风",
                            ],
                            "左右": [
                                "horizontal",
                                "left_right",
                                "lr",
                                "左右",
                                "左右扫风",
                            ],
                            # 垂直/上下扫风
                            "vertical": [
                                "vertical",
                                "up_down",
                                "ud",
                                "上下",
                                "上下扫风",
                            ],
                            "up_down": [
                                "vertical",
                                "up_down",
                                "ud",
                                "上下",
                                "上下扫风",
                            ],
                            "上下": ["vertical", "up_down", "ud", "上下", "上下扫风"],
                            # 关闭扫风
                            "off": ["off", "none", "关闭", "关闭扫风"],
                            "none": ["off", "none", "关闭", "关闭扫风"],
                            "关闭": ["off", "none", "关闭", "关闭扫风"],
                        }

                        mapped_mode = None
                        # 查找输入模式对应的所有可能值
                        possible_modes = swing_mode_mapping.get(
                            swing_mode, [swing_mode]
                        )

                        # 在设备支持的模式中查找匹配
                        for supported_mode in supported_swing_modes:
                            if supported_mode in possible_modes:
                                mapped_mode = supported_mode
                                break
                            # 反向查找：检查支持的模式是否在映射表中
                            for key, values in swing_mode_mapping.items():
                                if supported_mode in values and swing_mode in values:
                                    mapped_mode = supported_mode
                                    break
                            if mapped_mode:
                                break

                        if mapped_mode:
                            _LOGGER.info(f"映射扫风模式: {swing_mode} -> {mapped_mode}")
                            swing_mode = mapped_mode
                        else:
                            _LOGGER.error(f"无法映射扫风模式: {swing_mode}")
                            return False

                await self.hass.services.async_call(
                    domain,
                    "set_swing_mode",
                    {"entity_id": entity_id, "swing_mode": swing_mode},
                )
            elif action == "set_preset_mode" and domain == "climate":
                preset_mode = kwargs.get("preset_mode")
                if not preset_mode:
                    _LOGGER.error(f"缺少 preset_mode 参数")
                    return False
                _LOGGER.info(f"设置预设模式: {preset_mode}")
                await self.hass.services.async_call(
                    domain,
                    "set_preset_mode",
                    {"entity_id": entity_id, "preset_mode": preset_mode},
                )
            else:
                _LOGGER.error(f"不支持的动作: {action}")
                return False

            _LOGGER.info(f"设备控制成功: {entity_id}")
            return True

        except Exception as e:
            _LOGGER.error(f"控制设备失败 {entity_id}: {e}")
            return False

    async def generate_qr_code(self, data: Dict[str, Any]):
        """生成二维码"""
        try:
            client_name = data.get("client_name", "default")

            # 生成API token
            token = self.generate_api_token(client_name)

            # 获取本地IP（现在是异步的）
            local_ip = await self._get_local_ip()
            api_base_url = f"http://{local_ip}:8123{API_ENDPOINT}"

            # 构建API信息
            api_info = {
                "api_base_url": api_base_url,
                "token": token,
                "client_name": client_name,
                "generated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "expires_at": (datetime.now() + timedelta(hours=24)).isoformat(),
            }

            # 在执行器中生成二维码（因为qrcode.make可能涉及图像处理）
            qr_base64 = await self.hass.async_add_executor_job(
                self._generate_qr_code_blocking, json.dumps(api_info)
            )

            # 存储当前二维码和API信息
            self.current_qr_code = qr_base64
            self.current_api_info = api_info

            # 发送通知
            await self._send_qr_notification(qr_base64, api_info)

            _LOGGER.info(f"已生成新的二维码，客户端: {client_name}")

        except Exception as e:
            _LOGGER.error(f"生成二维码失败: {e}")
            raise

    def _generate_qr_code_blocking(self, data: str) -> str:
        """在执行器中运行的阻塞二维码生成操作"""
        try:
            # 生成二维码
            qr = qrcode.QRCode(version=1, box_size=10, border=5)
            qr.add_data(data)
            qr.make(fit=True)

            # 创建二维码图像 - 修复：使用qr对象的make_image方法
            img = qr.make_image(fill_color="black", back_color="white")

            # 转换为base64
            buffer = io.BytesIO()
            img.save(buffer, format="PNG")
            qr_base64 = base64.b64encode(buffer.getvalue()).decode()

            return qr_base64
        except Exception as e:
            _LOGGER.error(f"二维码生成失败: {e}")
            raise

    async def _send_qr_notification(self, qr_base64: str, api_info: Dict[str, Any]):
        """发送包含二维码的通知"""
        try:
            # 简化的通知内容，只显示二维码
            message = f"""
🌉 **设备桥接二维码**

📱 扫描二维码连接设备

base_url: {api_info["api_base_url"]}

<img src="data:image/png;base64,{qr_base64}" style="max-width: 300px; margin: 20px auto; display: block;">
            """

            # 发送持久化通知
            await self.hass.services.async_call(
                "persistent_notification",
                "create",
                {
                    "title": "🌉 设备桥接二维码",
                    "message": message,
                    "notification_id": "device_bridge_qr_code",
                },
            )

            _LOGGER.info("二维码通知已发送")

        except Exception as e:
            _LOGGER.error(f"发送二维码通知失败: {e}")

    async def _get_local_ip(self) -> str:
        """获取用户配置的IP地址"""
        # 直接使用用户在配置中输入的 IP/域名
        ip = self.entry.data.get("ip", "").strip()
        if ip:
            return ip

        # 如果用户没有配置，返回 localhost 作为默认值
        return "localhost"


class DeviceListView(HomeAssistantView):
    """设备列表API视图"""

    requires_auth = False
    url = "/api/device_bridge/devices"
    name = "api:device_bridge:devices"
    cors_allowed = True

    def __init__(self, manager: DeviceBridgeManager):
        self.manager = manager

    async def get(self, request):
        """获取设备列表"""
        try:
            # 删除记录浏览器地址栏域名/IP的代码

            # 验证token
            token = request.headers.get("Authorization", "").replace("Bearer ", "")
            if not self.manager.validate_token(token):
                return web.json_response({"error": "Invalid token"}, status=401)

            devices = await self.manager.get_aggregated_devices()
            return web.json_response(devices)
        except Exception as e:
            _LOGGER.error(f"Error in device list API: {e}")
            return web.json_response({"error": "Internal server error"}, status=500)

    # 移除 options 方法


class DeviceControlView(HomeAssistantView):
    """设备控制API视图"""

    requires_auth = False
    url = "/api/device_bridge/control"
    name = "api:device_bridge:control"
    cors_allowed = True

    def __init__(self, manager: DeviceBridgeManager):
        self.manager = manager

    async def post(self, request):
        """控制设备"""
        try:
            # 删除记录浏览器地址栏域名/IP的代码

            # 验证token
            token = request.headers.get("Authorization", "").replace("Bearer ", "")
            if not self.manager.validate_token(token):
                return web.json_response({"error": "Invalid token"}, status=401)

            data = await request.json()
            entity_id = data.get("entity_id")
            action = data.get("action")

            if not entity_id or not action:
                return web.json_response(
                    {"error": "Missing entity_id or action"}, status=400
                )

            # 提取额外参数
            kwargs = {k: v for k, v in data.items() if k not in ["entity_id", "action"]}

            success = await self.manager.control_device(entity_id, action, **kwargs)

            if success:
                return web.json_response({"success": True})
            else:
                return web.json_response({"error": "Control failed"}, status=500)

        except Exception as e:
            _LOGGER.error(f"Error in device control API: {e}")
            return web.json_response({"error": "Internal server error"}, status=500)

    # 移除 options 方法


class DeviceStatusView(HomeAssistantView):
    """设备状态API视图"""

    requires_auth = False
    url = "/api/device_bridge/status/{entity_id}"
    name = "api:device_bridge:status"
    cors_allowed = True

    def __init__(self, manager: DeviceBridgeManager):
        self.manager = manager

    async def get(self, request):
        """获取设备状态"""
        try:
            # 删除记录浏览器地址栏域名/IP的代码

            # 验证token
            token = request.headers.get("Authorization", "").replace("Bearer ", "")
            if not self.manager.validate_token(token):
                return web.json_response({"error": "Invalid token"}, status=401)

            entity_id = request.match_info["entity_id"]
            state = self.manager.hass.states.get(entity_id)

            if state is None:
                return web.json_response({"error": "Entity not found"}, status=404)

            return web.json_response(
                {
                    "entity_id": entity_id,
                    "state": state.state,
                    "attributes": dict(state.attributes),
                    "last_changed": state.last_changed.isoformat(),
                    "last_updated": state.last_updated.isoformat(),
                }
            )
        except Exception as e:
            _LOGGER.error(f"Error in device status API: {e}")
            return web.json_response({"error": "Internal server error"}, status=500)

    # 移除 options 方法


class QRCodeView(HomeAssistantView):
    """二维码API视图"""

    requires_auth = False
    url = "/api/device_bridge/qr_code"
    name = "api:device_bridge:qr_code"
    cors_allowed = True

    def __init__(self, manager: DeviceBridgeManager):
        self.manager = manager

    async def get(self, request):
        """获取当前二维码及API信息"""
        try:
            # 删除记录浏览器地址栏域名/IP的代码

            if self.manager.current_qr_data and hasattr(
                self.manager, "current_api_info"
            ):
                return web.json_response(
                    {
                        "success": True,
                        "qr_code": self.manager.current_qr_data,
                        "api_info": self.manager.current_api_info,
                    }
                )
            else:
                return web.json_response({"error": "No QR code available"}, status=404)
        except Exception as e:
            _LOGGER.error(f"Error in QR code API: {e}")
            return web.json_response({"error": "Internal server error"}, status=500)

    async def post(self, request):
        """生成新的二维码"""
        try:
            # 删除记录浏览器地址栏域名/IP的代码

            data = await request.json()
            client_name = data.get("client_name", "default")
            await self.manager.generate_qr_code({"client_name": client_name})
            return web.json_response({"success": True})
        except Exception as e:
            _LOGGER.error(f"Error generating QR code: {e}")
            return web.json_response({"error": "Internal server error"}, status=500)

    # 移除 options 方法


class DeviceWebSocketView(HomeAssistantView):
    """WebSocket视图用于实时状态推送"""

    url = "/api/device_bridge/ws"
    name = "api:device_bridge:ws"
    requires_auth = False

    def __init__(self, bridge_manager):
        self.bridge_manager = bridge_manager
        self.connections = set()
        self.subscriptions = {}  # 存储每个连接的订阅设备列表
        self.client_identifiers = {}  # 存储连接对应的客户端标识
        self.state_listener = None

    async def get(self, request):
        """处理WebSocket连接"""
        ws = web.WebSocketResponse()
        await ws.prepare(request)

        # 验证token
        token = request.query.get("token")
        if not self.bridge_manager.validate_token(token):
            await ws.close(code=4001, message="Invalid token")
            return ws

        # 获取客户端标识符
        client_id = self._get_client_identifier(token, request)

        # 检查该客户端是否有持久化订阅
        persistent_entities = self.bridge_manager.get_persistent_subscriptions(
            client_id
        )

        # 发送连接成功消息，包含订阅恢复信息
        await ws.send_json(
            {
                "type": "connection_established",
                "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "message": "WebSocket连接已建立",
                "has_persistent_subscriptions": len(persistent_entities) > 0,
                "persistent_entities_count": len(persistent_entities),
            }
        )

        # 存储客户端信息
        self.client_identifiers[ws] = client_id

        # 添加连接
        self.connections.add(ws)
        self.subscriptions[ws] = set()  # 初始化订阅列表

        # 如果有持久化订阅，自动恢复
        if persistent_entities:
            _LOGGER.info(
                f"为客户端 {client_id} 自动恢复持久化订阅: {persistent_entities}"
            )
            await self._handle_subscription(ws, persistent_entities, persistent=True)
        else:
            _LOGGER.info(f"客户端 {client_id} 无持久化订阅需要恢复")

        # 启动状态监听（如果尚未启动）
        if not self.state_listener:
            await self._start_state_listener()

        _LOGGER.info(
            f"WebSocket连接已建立，客户端: {client_id}, 当前连接数: {len(self.connections)}"
        )

        try:
            async for msg in ws:
                if msg.type == web.WSMsgType.TEXT:
                    # 处理客户端消息
                    await self._handle_client_message(ws, msg.data)
                elif msg.type == web.WSMsgType.ERROR:
                    _LOGGER.error(f"WebSocket错误: {ws.exception()}")
        except Exception as e:
            _LOGGER.error(f"WebSocket处理异常: {e}")
        finally:
            # 清理连接
            if ws in self.connections:
                self.connections.remove(ws)
            if ws in self.subscriptions:
                del self.subscriptions[ws]
            if ws in self.client_identifiers:
                del self.client_identifiers[ws]
            _LOGGER.info(f"WebSocket连接已关闭，剩余连接数: {len(self.connections)}")

        return ws

    def _get_client_identifier(self, token: str, request) -> str:
        """获取客户端唯一标识符"""
        # 使用token作为主要标识符，确保稳定性
        token_info = self.bridge_manager.api_tokens.get(token, {})
        client_name = token_info.get("client_name", "unknown")

        # 为每个token生成固定的客户端ID，不依赖IP和User-Agent
        # 这样容器重启后客户端标识符保持不变
        client_id = f"{client_name}_{hash(token)}"

        return client_id

    async def _restore_persistent_subscriptions(self, ws, client_id: str):
        """恢复持久化订阅"""
        persistent_entities = self.bridge_manager.get_persistent_subscriptions(
            client_id
        )
        if persistent_entities:
            _LOGGER.info(f"为客户端 {client_id} 恢复持久化订阅: {persistent_entities}")
            await self._handle_subscription(ws, persistent_entities, persistent=True)

    async def _handle_subscription(self, ws, entity_ids, persistent=False):
        """处理订阅请求"""
        if not entity_ids:
            await ws.send_json({"type": "error", "message": "订阅的设备列表不能为空"})
            return

        # 验证设备是否存在
        valid_entity_ids = []
        for entity_id in entity_ids:
            state = self.bridge_manager.hass.states.get(entity_id)
            if state:
                valid_entity_ids.append(entity_id)
            else:
                _LOGGER.warning(f"设备不存在: {entity_id}")

        # 更新订阅列表
        self.subscriptions[ws].update(valid_entity_ids)

        # 如果是持久化订阅，保存到文件
        if persistent and valid_entity_ids:
            client_id = self.client_identifiers.get(ws)
            if client_id:
                self.bridge_manager.add_persistent_subscription(
                    client_id, valid_entity_ids
                )

        # 只记录日志，不发送任何确认消息
        _LOGGER.info(f"客户端已订阅 {len(valid_entity_ids)} 个设备: {valid_entity_ids}")

    async def _handle_unsubscription(self, ws, entity_ids, persistent=False):
        """处理取消订阅请求"""
        if not entity_ids:
            # 取消所有订阅
            removed_entities = list(self.subscriptions[ws])
            self.subscriptions[ws].clear()

            # 如果是持久化取消订阅，从文件中移除
            if persistent:
                client_id = self.client_identifiers.get(ws)
                if client_id:
                    self.bridge_manager.remove_persistent_subscription(client_id)
        else:
            # 取消指定设备的订阅
            removed_entities = entity_ids
            self.subscriptions[ws] = self.subscriptions[ws] - set(entity_ids)

            # 如果是持久化取消订阅，从文件中移除指定设备
            if persistent:
                client_id = self.client_identifiers.get(ws)
                if client_id:
                    self.bridge_manager.remove_persistent_subscription(
                        client_id, entity_ids
                    )

        _LOGGER.info(f"客户端已取消订阅设备: {removed_entities}")
        await ws.send_json(
            {
                "type": "unsubscription_confirmed",
                "unsubscribed_entities": removed_entities,
                "persistent": persistent,
                "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            }
        )

    async def _handle_client_message(self, ws, message_data):
        """处理客户端消息"""
        try:
            data = json.loads(message_data)
            message_type = data.get("type")

            if message_type == "subscribe":
                # 订阅设备状态变化
                entity_ids = data.get("entity_ids", [])
                # 默认启用持久化订阅，确保容器重启后自动恢复
                persistent = data.get("persistent", True)
                await self._handle_subscription(ws, entity_ids, persistent)
            elif message_type == "unsubscribe":
                # 取消订阅
                entity_ids = data.get("entity_ids", [])
                # 默认持久化取消订阅
                persistent = data.get("persistent", True)
                await self._handle_unsubscription(ws, entity_ids, persistent)
            elif message_type == "ping":
                # 心跳响应
                await ws.send_json(
                    {
                        "type": "pong",
                        "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                    }
                )
            elif message_type == "get_persistent_subscriptions":
                # 获取当前持久化订阅
                client_id = self.client_identifiers.get(ws)
                if client_id:
                    persistent_entities = (
                        self.bridge_manager.get_persistent_subscriptions(client_id)
                    )
                    await ws.send_json(
                        {
                            "type": "persistent_subscriptions",
                            "entities": persistent_entities,
                            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                        }
                    )
            else:
                _LOGGER.warning(f"未知的消息类型: {message_type}")

        except json.JSONDecodeError:
            _LOGGER.error("无法解析客户端消息JSON")
        except Exception as e:
            _LOGGER.error(f"处理客户端消息失败: {e}")

    async def _start_state_listener(self):
        """启动状态变化监听器"""

        async def state_changed_listener(event):
            """处理状态变化事件"""
            entity_id = event.data.get("entity_id")
            new_state = event.data.get("new_state")
            old_state = event.data.get("old_state")

            if not entity_id or not new_state:
                return

            # 正确处理old_state和new_state对象
            old_state_value = None
            if old_state is not None:
                old_state_value = (
                    old_state.state if hasattr(old_state, "state") else None
                )

            new_state_value = new_state.state if hasattr(new_state, "state") else None
            new_attributes = (
                dict(new_state.attributes) if hasattr(new_state, "attributes") else {}
            )

            # 获取设备品类类型（domain）
            device_domain = entity_id.split(".")[0] if entity_id else "unknown"

            # 广播状态变化给所有订阅了该设备的连接
            for ws, subscribed_entities in self.subscriptions.items():
                if entity_id in subscribed_entities and not ws.closed:
                    try:
                        await ws.send_json(
                            {
                                "type": "state_changed",
                                "entity_id": entity_id,
                                "device_domain": device_domain,
                                "old_state": old_state_value,
                                "new_state": new_state_value,
                                "attributes": new_attributes,
                                "timestamp": datetime.now().strftime(
                                    "%Y-%m-%d %H:%M:%S"
                                ),
                            }
                        )
                    except Exception as e:
                        _LOGGER.error(f"发送状态变化消息失败: {e}")
                        # 如果发送失败，可能是连接已断开，清理连接
                        if ws in self.connections:
                            self.connections.remove(ws)
                        if ws in self.subscriptions:
                            del self.subscriptions[ws]

        # 注册状态变化监听器
        self.state_listener = self.bridge_manager.hass.bus.async_listen(
            "state_changed", state_changed_listener
        )
        _LOGGER.info("设备状态变化监听器已启动")

    async def cleanup(self):
        """清理资源"""
        if self.state_listener:
            self.state_listener()
            self.state_listener = None

        # 关闭所有连接
        for ws in list(self.connections):
            if not ws.closed:
                await ws.close()

        self.connections.clear()
        self.subscriptions.clear()
        _LOGGER.info("WebSocket资源已清理")
